import { defineStore } from 'pinia'
import { ref, markRaw } from 'vue'
import { ethers } from 'ethers'
import contractConfig from '@/config/contract.json'
import contractABI from '@/config/Stockimprove.json'

export const useContractStore = defineStore('contract', () => {
  // 使用 ref 但不让 Vue 追踪 ethers 对象（避免 Proxy 包装）
  const provider = ref(null)
  const signer = ref(null)
  const contract = ref(null)
  const currentAccount = ref(null)
  const contractOwner = ref(null)
  const networkId = ref(null)
  const networkName = ref(null)
  
  // 切换到本地网络
  const switchToLocalNetwork = async () => {
    try {
      // 尝试切换到链 ID 31337 (Hardhat)
      await window.ethereum.request({
        method: 'wallet_switchEthereumChain',
        params: [{ chainId: '0x7A69' }], // 31337 的十六进制
      })
      console.log('成功切换到 Hardhat 网络')
      return true
    } catch (switchError) {
      // 如果网络不存在，尝试添加
      if (switchError.code === 4902) {
        try {
          await window.ethereum.request({
            method: 'wallet_addEthereumChain',
            params: [{
              chainId: '0x7A69', // 31337
              chainName: 'Localhost 8545',
              nativeCurrency: {
                name: 'Ethereum',
                symbol: 'ETH',
                decimals: 18
              },
              rpcUrls: ['http://127.0.0.1:8545'],
              blockExplorerUrls: null
            }]
          })
          console.log('成功添加并切换到本地网络')
          return true
        } catch (addError) {
          console.error('添加网络失败:', addError)
          return false
        }
      } else if (switchError.code === 4001) {
        console.log('用户取消切换网络')
        return false
      } else {
        console.error('切换网络失败:', switchError)
        return false
      }
    }
  }
  
  // 检查网络
  const checkNetwork = async () => {
    try {
      // 使用 window.ethereum 直接获取 chainId，避免 provider 初始化问题
      const chainIdHex = await window.ethereum.request({ method: 'eth_chainId' })
      networkId.value = parseInt(chainIdHex, 16)
      
      // 根据chainId确定网络名称
      const networkNames = {
        1: 'Ethereum Mainnet',
        3: 'Ropsten',
        4: 'Rinkeby',
        5: 'Goerli',
        11155111: 'Sepolia',
        31337: 'Hardhat Local',
        1337: 'Localhost'
      }
      
      networkName.value = networkNames[networkId.value] || `Unknown (${networkId.value})`
      console.log('当前网络:', networkName.value, '链ID:', networkId.value)
      
      // 检查是否是本地网络
      if (networkId.value !== 31337 && networkId.value !== 1337) {
        console.warn('警告：合约部署在本地网络，但当前连接的是:', networkName.value)
        
        // 询问用户是否自动切换
        const shouldSwitch = confirm(
          `⚠️ 网络不匹配\n\n` +
          `当前网络: ${networkName.value}\n` +
          `需要网络: Localhost 8545 (Hardhat)\n\n` +
          `是否自动切换到本地网络？`
        )
        
        if (shouldSwitch) {
          const switched = await switchToLocalNetwork()
          if (switched) {
            // 切换成功，重新加载页面
            window.location.reload()
            return true
          }
        }
        
        return false
      }
      
      return true
    } catch (error) {
      console.error('检查网络失败:', error)
      return false
    }
  }
  
  // 初始化 Web3 Provider (MetaMask)
  const initProvider = async () => {
    if (typeof window.ethereum !== 'undefined') {
      try {
        // 请求账户访问
        const accounts = await window.ethereum.request({ 
          method: 'eth_requestAccounts' 
        })
        
        if (!accounts || accounts.length === 0) {
          console.error('未获取到账户')
          alert('请在 MetaMask 中连接至少一个账户')
          return false
        }
        
        currentAccount.value = accounts[0]
        console.log('当前账户:', currentAccount.value)
        
        // 检查网络（使用原生 API，不依赖 ethers）
        try {
          const networkOk = await checkNetwork()
          if (!networkOk) {
            console.warn('网络可能不匹配，继续尝试连接...')
          }
        } catch (networkError) {
          console.warn('检查网络时出错，继续连接:', networkError)
        }
        
        // 创建 provider（使用 ethers v5 API）
        // 使用 markRaw 防止 Vue 把 ethers 对象包装成 Proxy
        provider.value = markRaw(new ethers.providers.Web3Provider(window.ethereum))
        console.log('Provider 创建成功')
        
        // 获取 signer（ethers v5 同步调用）
        signer.value = markRaw(provider.value.getSigner())
        console.log('Signer 创建成功')
        
        // 获取地址
        const address = await signer.value.getAddress()
        console.log('Signer 地址获取成功:', address)
        
        // 初始化合约（也使用 markRaw）
        contract.value = markRaw(new ethers.Contract(
          contractConfig.contractAddress,
          contractABI.abi,
          signer.value
        ))
        console.log('合约初始化成功，地址:', contractConfig.contractAddress)
        
        // 获取合约所有者
        try {
          contractOwner.value = await contract.value.getContractOwner()
          console.log('合约所有者:', contractOwner.value)
        } catch (ownerError) {
          console.warn('获取合约所有者失败，可能合约未部署或网络不匹配:', ownerError)
          // 即使获取所有者失败，也不影响基本连接
          contractOwner.value = null
        }
        
        // 监听账户变化
        window.ethereum.on('accountsChanged', (accounts) => {
          if (accounts.length > 0) {
            currentAccount.value = accounts[0]
            window.location.reload()
          }
        })
        
        // 监听网络变化
        window.ethereum.on('chainChanged', () => {
          window.location.reload()
        })
        
        console.log('MetaMask 连接成功！')
        return true
      } catch (error) {
        console.error('初始化 Web3 失败:', error)
        
        // 更详细的错误信息
        if (error.code === 4001) {
          alert('用户拒绝了连接请求，请在 MetaMask 中批准连接')
        } else if (error.code === -32002) {
          alert('MetaMask 连接请求待处理，请检查 MetaMask 扩展')
        } else {
          alert('MetaMask 连接失败: ' + (error.message || '未知错误') + '\n\n请确保：\n1. MetaMask 已安装并解锁\n2. 已连接到正确的网络（Localhost 8545）\n3. 合约已正确部署')
        }
        return false
      }
    } else {
      alert('请安装 MetaMask 浏览器插件!')
      return false
    }
  }
  
  // 检查是否是合约所有者
  const isContractOwner = () => {
    if (!currentAccount.value || !contractOwner.value) return false
    return currentAccount.value.toLowerCase() === contractOwner.value.toLowerCase()
  }
  
  // 添加股票
  const addStock = async (name, description, totalShares) => {
    if (!contract.value) throw new Error('合约未初始化')
    console.log('准备创建股票:', { name, description, totalShares })
    const tx = await contract.value.addStock(name, description, totalShares)
    console.log('创建交易已发送:', tx.hash)
    await tx.wait()
    console.log('创建交易已确认')
    return tx
  }
  
  // 添加股票并分配
  const addStockWithAllocation = async (name, description, totalShares, recipients, shares) => {
    if (!contract.value) throw new Error('合约未初始化')
    const tx = await contract.value.addStockWithAllocation(
      name, description, totalShares, recipients, shares
    )
    await tx.wait()
    return tx
  }
  
  // 删除股票
  const removeStock = async (stockId) => {
    if (!contract.value) throw new Error('合约未初始化')
    console.log('准备删除股票:', stockId)
    const tx = await contract.value.removeStock(stockId)
    console.log('删除交易已发送:', tx.hash)
    await tx.wait()
    console.log('删除交易已确认，股票已被删除')
    return tx
  }
  
  // 更新股票
  const updateStock = async (stockId, name, description, totalShares) => {
    if (!contract.value) throw new Error('合约未初始化')
    console.log('准备更新股票:', { stockId, name, description, totalShares })
    const tx = await contract.value.updateStock(stockId, name, description, totalShares)
    console.log('更新交易已发送:', tx.hash)
    await tx.wait()
    console.log('更新交易已确认')
    return tx
  }
  
  // 转让股份
  const transferShares = async (stockId, from, to, shares) => {
    if (!contract.value) throw new Error('合约未初始化')
    const tx = await contract.value.transferShares(stockId, from, to, shares)
    await tx.wait()
    return tx
  }
  
  // 获取股票信息
  const getStock = async (stockId) => {
    if (!contract.value) throw new Error('合约未初始化')
    const result = await contract.value.getStock(stockId)
    console.log(`getStock(${stockId}) 原始返回:`, result)
    
    // ethers v5 返回 BigNumber，需要用 .toNumber() 转换
    const stock = {
      stockId: result[0].toNumber(),
      name: result[1],
      description: result[2],
      totalShares: result[3].toNumber(),
      shareholderList: result[4],
      timestamp: result[5].toNumber()
    }
    console.log(`getStock(${stockId}) 转换后:`, stock)
    return stock
  }
  
  // 获取持股数量
  const getShareholderShares = async (stockId, shareholder) => {
    if (!contract.value) throw new Error('合约未初始化')
    const shares = await contract.value.getShareholderShares(stockId, shareholder)
    // ethers v5 返回 BigNumber
    return shares.toNumber()
  }
  
  // 获取所有股东
  const getAllShareholders = async (stockId) => {
    if (!contract.value) throw new Error('合约未初始化')
    const result = await contract.value.getAllShareholders(stockId)
    return {
      addresses: result[0],
      shares: result[1].map(s => s.toNumber())  // ethers v5 BigNumber
    }
  }
  
  // 获取下一个股票ID
  const getNextStockId = async () => {
    if (!contract.value) throw new Error('合约未初始化')
    const id = await contract.value.getNextStockId()
    // ethers v5 返回 BigNumber
    return id.toNumber()
  }
  
  return {
    provider,
    signer,
    contract,
    currentAccount,
    contractOwner,
    networkId,
    networkName,
    initProvider,
    switchToLocalNetwork,
    checkNetwork,
    isContractOwner,
    addStock,
    addStockWithAllocation,
    removeStock,
    updateStock,
    transferShares,
    getStock,
    getShareholderShares,
    getAllShareholders,
    getNextStockId
  }
})

